home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
comm
/
mail
/
Mutt089src.lha
/
Mutt-0.89i-AMIGA
/
src
/
pgpkey.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-28
|
13KB
|
583 lines
/*
* Copyright (C) 1996,1997 Michael R. Elkins <me@cs.hmc.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!
*
* Legal for distribution in the U.S./Canada ONLY! Exporting this file
* outside of the U.S./Canada may be in violation of ITAR regulations!
*/
#include "mutt.h"
#include "mutt_curses.h"
#include "mutt_menu.h"
#include "mime.h"
#include "pgp.h"
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#ifdef _PGPPATH
static struct pgp_cache {
char *what;
char *dflt;
struct pgp_cache *next;
} * id_defaults = NULL;
typedef struct
{
KEYINFO *k;
PGPUID *a;
} pgp_key_t;
static char trust_flags[] = "?- +";
static char *pgp_key_abilities(int flags)
{
static char buff[3];
if(!(flags & KEYFLAG_CANENCRYPT))
buff[0] = '-';
else if(flags & KEYFLAG_PREFER_SIGNING)
buff[0] = '.';
else
buff[0] = 'e';
if(!(flags & KEYFLAG_CANSIGN))
buff[1] = '-';
else if(flags & KEYFLAG_PREFER_ENCRYPTION)
buff[1] = '.';
else
buff[1] = 's';
buff[2] = '\0';
return buff;
}
static void pgp_entry (char *s, size_t l, MUTTMENU *menu, int num)
{
pgp_key_t *KeyTable = (pgp_key_t *) menu->data;
snprintf (s, l, "%4d %c%c %4d/0x%s %-4s %2s %s",
num + 1,
(option(OPTPGPCHECKTRUST) ?
trust_flags[KeyTable[num].a->trust & 0x03] : ' '),
(option(OPTPGPCHECKTRUST) &&
(KeyTable[num].k->flags & KEYFLAG_CRITICAL) ?
'c' : ' '),
KeyTable[num].k->keylen,
pgp_keyid(KeyTable[num].k),
KeyTable[num].k->algorithm,
pgp_key_abilities(KeyTable[num].k->flags),
KeyTable[num].a->addr);
}
static int pgp_search (MUTTMENU *m, regex_t *re, int n)
{
char buf[LONG_STRING];
pgp_entry (buf, sizeof (buf), m, n);
return (regexec (re, buf, 0, NULL, 0));
}
static int pgp_compare (const void *a, const void *b)
{
pgp_key_t *s = (pgp_key_t *) a;
pgp_key_t *t = (pgp_key_t *) b;
return (strcasecmp (s->a->addr, t->a->addr));
}
static char *pgp_select_key (LIST *keys, ADDRESS *p, const char *s)
{
int keymax;
pgp_key_t *KeyTable;
MUTTMENU *menu;
LIST *a;
int i;
int done = 0;
LIST *l;
char *id = NULL, helpstr[SHORT_STRING], buf[LONG_STRING];
char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
FILE *fp, *devnull;
pid_t thepid;
KEYINFO *info;
for (i = 0, l = keys; l; l = l->next)
{
int did_main_key = 0;
info = (KEYINFO *) l->data;
a = info->address;
retry1:
for (; a; i++, a = a->next)
;
if(!did_main_key && info->flags & KEYFLAG_SUBKEY && info->mainkey)
{
did_main_key = 1;
a = info->mainkey->address;
goto retry1;
}
}
if (i == 0) return NULL;
keymax = i;
KeyTable = safe_malloc (sizeof (pgp_key_t) * i);
for (i = 0, l = keys; l; l = l->next)
{
int did_main_key = 0;
info = (KEYINFO *)l->data;
a = info->address;
retry2:
for (; a ; i++, a = a->next)
{
KeyTable[i].k = (KEYINFO *) l->data;
KeyTable[i].a = (PGPUID *)a->data;
}
if(!did_main_key && info->flags & KEYFLAG_SUBKEY && info->mainkey)
{
did_main_key = 1;
a = info->mainkey->address;
goto retry2;
}
}
qsort (KeyTable, i, sizeof (pgp_key_t), pgp_compare);
helpstr[0] = 0;
mutt_make_help (buf, sizeof (buf), "Exit ", MENU_PGP, OP_EXIT);
strcat (helpstr, buf);
mutt_make_help (buf, sizeof (buf), "Select ", MENU_PGP,
OP_GENERIC_SELECT_ENTRY);
strcat (helpstr, buf);
mutt_make_help (buf, sizeof (buf), "Check key ", MENU_PGP, OP_VERIFY_KEY);
strcat (helpstr, buf);
mutt_make_help (buf, sizeof (buf), "Help", MENU_PGP, OP_HELP);
strcat (helpstr, buf);
menu = mutt_new_menu ();
menu->max = keymax;
menu->make_entry = pgp_entry;
menu->search = pgp_search;
menu->menu = MENU_PGP;
menu->help = helpstr;
menu->data = KeyTable;
strfcpy (buf, "PGP keys matching ", sizeof (buf));
if (p)
rfc822_address (buf, sizeof (buf) - strlen (buf), p);
else
strcat (buf, s);
menu->title = buf;
while (!done)
{
switch (mutt_menuLoop (menu))
{
case OP_VERIFY_KEY:
mutt_mktemp (tempfile);
if ((devnull = fopen ("/dev/null", "w")) == NULL)
{
mutt_perror ("Can't open /dev/null");
break;
}
if ((fp = safe_fopen (tempfile, "w")) == NULL)
{
fclose (devnull);
mutt_perror ("Can't create temporary file");
break;
}
mutt_message ("Invoking PGP...");
if((thepid = pgp_invoke_verify_key(NULL, NULL, NULL, -1,
fileno(fp), fileno(devnull),
pgp_keyid(KeyTable[menu->current].k))) == -1)
{
mutt_perror ("Can't create filter");
unlink (tempfile);
fclose (fp);
fclose (devnull);
}
mutt_wait_filter (thepid);
fclose (fp);
fclose (devnull);
mutt_clear_error ();
snprintf(cmd, sizeof(cmd), "Key ID: 0x%s", pgp_keyid(KeyTable[menu->current].k));
mutt_do_pager (cmd, tempfile, 0);
menu->redraw = REDRAW_FULL;
break;
case OP_VIEW_ID:
mutt_message (KeyTable[menu->current].a->addr);
break;
case OP_GENERIC_SELECT_ENTRY:
if (option (OPTPGPCHECKTRUST) &&
(KeyTable[menu->current].a->trust & 0x03) < 3)
{
char *s = "";
char buff[LONG_STRING];
switch (KeyTable[menu->current].a->trust & 0x03)
{
case 0: s = "This ID's trust level is undefined."; break;
case 1: s = "This ID is not trusted."; break;
case 2: s = "This ID is only marginally trusted."; break;
}
snprintf (buff, sizeof(buff), "%s Do you really want to use it?", s);
if (mutt_yesorno (buff, 0) != 1)
{
mutt_clear_error ();
break;
}
}
id = pgp_keyid(KeyTable[menu->current].k);
done = 1;
break;
case OP_EXIT:
id = NULL;
done = 1;
break;
}
}
mutt_menuDestroy (&menu);
safe_free ((void **) &KeyTable);
return (id);
}
char *pgp_ask_for_key (const char *ringfile, KEYINFO *udb, char *tag, char *whatfor,
short abilities)
{
KEYINFO *db;
char *key;
char resp[SHORT_STRING];
struct pgp_cache *l = NULL;
db = udb ? udb : pgp_read_keyring(ringfile);
resp[0] = 0;
if (whatfor)
{
for (l = id_defaults; l; l = l->next)
if (!strcasecmp (whatfor, l->what))
{
strcpy (resp, l->dflt);
break;
}
}
FOREVER
{
if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
{
if (!udb) pgp_closedb (db);
return NULL;
}
if (whatfor)
{
if (l)
{
safe_free ((void **)&l->dflt);
l->dflt = safe_strdup (resp);
}
else
{
l = safe_malloc (sizeof (struct pgp_cache));
l->next = id_defaults;
id_defaults = l;
l->what = safe_strdup (whatfor);
l->dflt = safe_strdup (resp);
}
}
if ((key = ki_getkeybystr (resp, db, abilities)))
{
key = safe_strdup (key);
if (!udb) pgp_closedb (db);
return (key);
}
BEEP ();
}
/* not reached */
}
/* generate a public key attachment */
BODY *pgp_make_key_attachment (char * tempf)
{
BODY *att;
char buff[LONG_STRING];
char tempfb[_POSIX_PATH_MAX];
char *id;
FILE *tempfp;
FILE *devnull;
struct stat sb;
pid_t thepid;
unset_option (OPTPGPCHECKTRUST);
if (!(id = pgp_ask_for_key (PgpPubring, NULL, "Please enter the key ID: ", NULL, 0)))
return NULL;
if (!tempf) {
mutt_mktemp (tempfb);
tempf = tempfb;
}
if ((tempfp = s